package com.andova.esgl.sample

import android.content.Context
import android.graphics.BitmapFactory
import android.opengl.GLES30
import android.opengl.GLSurfaceView
import android.opengl.GLUtils
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.andova.egl.MatrixState
import com.andova.egl.glesInitialize
import com.andova.ext.methodTime
import com.andova.cameraview.R
import com.andova.glplugin.GlFrameAnimPlugin
import com.andova.test.SampleTexture
import java.io.IOException
import java.io.InputStream
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10


class TextureActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val glsv = GLSurfaceView(this)
        setContentView(glsv)
        glsv.setEGLContextClientVersion(3)
        val vertexGlsl = getInstr(assets.open("vertex/simple_texture.glsl"))
        val fragmentGlsl = getInstr(assets.open("fragment/simple_texture.glsl"))
        glsv.setRenderer(TextureArrayRender(this))
//        glsv.setRenderer(SimpleTextureRender(vertexGlsl, fragmentGlsl, resources.openRawResource(R.raw.wall)))
    }

    private fun getInstr(instr: InputStream): String {
        return String(instr.readBytes())
    }
}

class SampleTextureRender(context: Context) : GLSurfaceView.Renderer {
    private val test = SampleTexture(context)
    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        GLES30.glViewport(0, 0, width, height)
    }

    override fun onDrawFrame(gl: GL10?) {
        GLES30.glClear(GLES30.GL_DEPTH_BUFFER_BIT or GLES30.GL_COLOR_BUFFER_BIT)
        test.drawAllTexture()
    }

    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        GLES30.glClearColor(0.5f, 0.5f, 0.5f, 1f)
        test.init()
//        GLES30.glEnable(GLES30.GL_DEPTH_TEST) // 打开深度检测
//        GLES30.glDisable(GLES30.GL_CULL_FACE) // 关闭背面剪裁
    }
}

class SimpleTextureRender(private val vertexGlsl: String, private val fragmentGlsl: String, private val bmpInstr: InputStream) : GLSurfaceView.Renderer {
    private var textureId: Int = -1
    private var triangle: Texture_Sample_Triangle? = null

    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        GLES30.glViewport(0, 0, width, height)
        val ratio = width / height.toFloat()
        MatrixState.setProjectFrustum(-ratio, ratio, -1f, 1f, 1f, 10f)
        MatrixState.setCamera(0f, 0f, 3f, 0f, 0f, 0f, 0f, 1.0f, 0.0f)
    }

    override fun onDrawFrame(gl: GL10?) {
        GLES30.glClear(GLES30.GL_DEPTH_BUFFER_BIT or GLES30.GL_COLOR_BUFFER_BIT)
        triangle?.drawFrame(textureId)
    }

    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        GLES30.glClearColor(0.5f, 0.5f, 0.5f, 1f)
        triangle = Texture_Sample_Triangle(vertexGlsl, fragmentGlsl)
        GLES30.glEnable(GLES30.GL_DEPTH_TEST) // 打开深度检测
        textureId = initSingleTexture()
        loadSimpleTexture(bmpInstr)
        GLES30.glDisable(GLES30.GL_CULL_FACE) // 关闭背面剪裁
    }

    private fun initSingleTexture(): Int {
        val texCount = 1
        val texIdArray = IntArray(texCount)
        GLES30.glGenTextures(texCount, texIdArray, 0) // 生成纹理id数组，最后一个参数表示偏移量
        val texId = texIdArray[0]
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, texId) // 绑定纹理id
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST) // 设置MIN采样方式
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR) // 设置MAG采样方式
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE) // 设置S轴拉伸方式
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE) // 设置T轴拉伸方式
        return texId
    }

    private fun loadSimpleTexture(instr: InputStream) {
        val bmp = try {
            BitmapFactory.decodeStream(instr)
        } catch (e: IOException) {
            null
        } finally {
            try {
                instr.close()
            } catch (t: IOException) {
            }
        }
        bmp ?: return
        GLUtils.texImage2D(
            GLES30.GL_TEXTURE_2D,   // 纹理类型
            0,                 // 纹理的层次
            bmp,                    // 纹理图像
            0                // 纹理边框尺寸
        )
        bmp.recycle()
    }
}

class Texture_Sample_Triangle(vertexGlsl: String, fragmentGlsl: String) {
    private var program = -1
    private var attrPosition = -1
    private var attrTexCoordinate = -1
    private var unifMVPMatrix = -1

    private val xAngle = 0f
    private val yAngle = 0f
    private val zAngle = 0f

    private var vertexBuffer: FloatBuffer? = null
    private var textureBuffer: FloatBuffer? = null

    init {
        program = glesInitialize(vertexGlsl, fragmentGlsl)
        initVertexData()
        attrPosition = GLES30.glGetAttribLocation(program, "aPosition")
        attrTexCoordinate = GLES30.glGetAttribLocation(program, "aTexCoordinate")
        unifMVPMatrix = GLES30.glGetUniformLocation(program, "uMVPMatrix")
    }

    companion object {
        const val VERTEX_COUNT = 3 // 顶点个数为3
    }

    /**
     * 初始化顶点数据
     */
    private fun initVertexData() {
        val unit = 0.15f
        // 顶点坐标数据数组
        val vertices: FloatArray = floatArrayOf(
            0 * unit, 11 * unit, 0f,    // 上
            -11 * unit, -11 * unit, 0f, // 左
            11 * unit, -11 * unit, 0f   // 右
        )
        // 创建顶点坐标数据缓冲
        val vbb = ByteBuffer.allocateDirect(vertices.size * 4).order(ByteOrder.nativeOrder())
        vertexBuffer = vbb.asFloatBuffer()
        vertexBuffer?.put(vertices) // 写入数据
        vertexBuffer?.position(0) // 设置起始位置
        // 顶点纹理坐标数据数组
        val textures: FloatArray = floatArrayOf(
            0.5f, 0f,   // 上
            0f, 1f,     // 左
            1f, 1f      // 右
        )
        textureBuffer = ByteBuffer.allocateDirect(textures.size * 4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(textures)?.apply { position(0) }
    }

    fun drawFrame(texId: Int) {
        GLES30.glUseProgram(program)
        MatrixState.apply {
            init()
            translate(0f, 0f, 1f)
            rotate(xAngle, 1f, 0f, 0f)
            rotate(yAngle, 0f, 1f, 0f)
            rotate(zAngle, 0f, 0f, 1f)
        }
        GLES30.glUniformMatrix4fv(unifMVPMatrix, 1, false, MatrixState.getFinalMatrix(), 0) // 将最终变换矩阵传入渲染管线
        GLES30.glVertexAttribPointer(attrPosition, 3, GLES30.GL_FLOAT, false, 3 * 4, vertexBuffer) // 将顶点位置数据传送进渲染管线
        GLES30.glVertexAttribPointer(attrTexCoordinate, 2, GLES30.GL_FLOAT, false, 2 * 4, textureBuffer) // 将纹理坐标数据传送进渲染管线
        GLES30.glEnableVertexAttribArray(attrPosition) // 启用顶点位置数据
        GLES30.glEnableVertexAttribArray(attrTexCoordinate) //启用顶点纹理坐标数据
        GLES30.glActiveTexture(GLES30.GL_TEXTURE0) // 激活指定的纹理单元
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, texId) // 绑定指定的纹理id
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, VERTEX_COUNT)
    }
}

class TextureArrayRender(context: Context) : GLSurfaceView.Renderer {
    private var rawArray = intArrayOf(
        R.raw.img_recognizing_00,
        R.raw.img_recognizing_01,
        R.raw.img_recognizing_02,
        R.raw.img_recognizing_03,
        R.raw.img_recognizing_04,
        R.raw.img_recognizing_05,
        R.raw.img_recognizing_06,
        R.raw.img_recognizing_07,
        R.raw.img_recognizing_08,
        R.raw.img_recognizing_09,
        R.raw.img_recognizing_10,
        R.raw.img_recognizing_11,
        R.raw.img_recognizing_12,
        R.raw.img_recognizing_13,
        R.raw.img_recognizing_14,
        R.raw.img_recognizing_15,
        R.raw.img_recognizing_16,
        R.raw.img_recognizing_17,
        R.raw.img_recognizing_18,
        R.raw.img_recognizing_19,
        R.raw.img_recognizing_20,
        R.raw.img_recognizing_21,
        R.raw.img_recognizing_22,
        R.raw.img_recognizing_23,
        R.raw.img_recognizing_24,
        R.raw.img_recognizing_25,
        R.raw.img_recognizing_26,
        R.raw.img_recognizing_27,
        R.raw.img_recognizing_28,
        R.raw.img_recognizing_29,
        R.raw.img_recognizing_30,
        R.raw.img_recognizing_31,
        R.raw.img_recognizing_32,
        R.raw.img_recognizing_33,
        R.raw.img_recognizing_34,
        R.raw.img_recognizing_35,
        R.raw.img_recognizing_36,
        R.raw.img_recognizing_37,
        R.raw.img_recognizing_38,
        R.raw.img_recognizing_39,
        R.raw.img_recognizing_40,
        R.raw.img_recognizing_41,
        R.raw.img_recognizing_42,
        R.raw.img_recognizing_43,
        R.raw.img_recognizing_44,
        R.raw.img_recognizing_45,
        R.raw.img_recognizing_46,
        R.raw.img_recognizing_47,
        R.raw.img_recognizing_48,
        R.raw.img_recognizing_49,
        R.raw.img_recognizing_50,
        R.raw.img_recognizing_51,
        R.raw.img_recognizing_52,
        R.raw.img_recognizing_53,
        R.raw.img_recognizing_54,
        R.raw.img_recognizing_55,
        R.raw.img_recognizing_56,
        R.raw.img_recognizing_57,
        R.raw.img_recognizing_58,
        R.raw.img_recognizing_59,
        R.raw.img_recognizing_60,
        R.raw.img_recognizing_61,
        R.raw.img_recognizing_62,
        R.raw.img_recognizing_63,
        R.raw.img_recognizing_64,
        R.raw.img_recognizing_65,
        R.raw.img_recognizing_66,
        R.raw.img_recognizing_67,
        R.raw.img_recognizing_68,
        R.raw.img_recognizing_69,
        R.raw.img_recognizing_70,
        R.raw.img_recognizing_71,
        R.raw.img_recognizing_72,
        R.raw.img_recognizing_73,
        R.raw.img_recognizing_74,
        R.raw.img_recognizing_75,
        R.raw.img_recognizing_76,
        R.raw.img_recognizing_77,
        R.raw.img_recognizing_78,
        R.raw.img_recognizing_79
    )
    private var plugin = GlFrameAnimPlugin(context, 610, 604, rawArray, 20)
    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {}
    override fun onDrawFrame(gl: GL10?) {
        methodTime { plugin.onPluginDraw(0, 0, 610, 604) }
    }

    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        GLES30.glClearColor(0.5f, 0.5f, 0.5f, 1f)
        plugin.onPluginCreate(0, 0)
    }
}